#ifndef __SPEECH_NLS__
#define __SPEECH_NLS__
#include <dirent.h>
#include <errno.h>
#include <pthread.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
#include <sys/io.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>

#include <ctime>
#include <fstream>
#include <iostream>
#include <map>
#include <string>
#include <vector>

#include "het_chatgpt.h"
#include "nlsClient.h"
#include "nlsEvent.h"
#include "nlsToken.h"
#include "profile_scan.h"

#include "speechRecognizerRequest.h"
#include "speechSynthesizerRequest.h"

#ifdef __cplusplus
extern "C" {
#endif
#define SELF_TESTING_TRIGGER
#define FRAME_16K_20MS     640
#define SAMPLE_RATE_16K    16000
#define DEFAULT_STRING_LEN 512
#define LOOP_TIMEOUT 60
#define LOG_TRIGGER
#define AUDIO_TEXT_LENGTH 1024

// 自定义线程参数
struct ParamStruct {
  char fileName[DEFAULT_STRING_LEN];
  char token[DEFAULT_STRING_LEN];
  char appkey[DEFAULT_STRING_LEN];
  char url[DEFAULT_STRING_LEN];
  char vipServerDomain[DEFAULT_STRING_LEN];
  char vipServerTargetDomain[DEFAULT_STRING_LEN];

  char text[AUDIO_TEXT_LENGTH];


  uint64_t startedConsumed;   /*started事件完成次数*/
  uint64_t firstConsumed;     /*首包完成次数*/
  uint64_t completedConsumed; /*completed事件次数*/
  uint64_t closeConsumed;     /*closed事件次数*/

  uint64_t failedConsumed;  /*failed事件次数*/
  uint64_t requestConsumed; /*发起请求次数*/

  uint64_t sendConsumed; /*sendAudio调用次数*/

  uint64_t startTotalValue; /*所有started完成时间总和*/
  uint64_t startAveValue;   /*started完成平均时间*/
  uint64_t startMaxValue;   /*调用start()到收到started事件最大用时*/
  uint64_t startMinValue;   /*调用start()到收到started事件最小用时*/

  uint64_t firstTotalValue; /*所有收到首包用时总和*/
  uint64_t firstAveValue;   /*收到首包平均时间*/
  uint64_t firstMaxValue;   /*调用start()到收到首包最大用时*/
  uint64_t firstMinValue;   /*调用start()到收到首包最小用时*/
  bool firstFlag;           /*是否收到首包的标记*/

  uint64_t endTotalValue; /*start()到completed事件的总用时*/
  uint64_t endAveValue;   /*start()到completed事件的平均用时*/
  uint64_t endMaxValue;   /*start()到completed事件的最大用时*/
  uint64_t endMinValue;   /*start()到completed事件的最小用时*/

  uint64_t closeTotalValue; /*start()到closed事件的总用时*/
  uint64_t closeAveValue;   /*start()到closed事件的平均用时*/
  uint64_t closeMaxValue;   /*start()到closed事件的最大用时*/
  uint64_t closeMinValue;   /*start()到closed事件的最小用时*/

  uint64_t sendTotalValue; /*单线程调用sendAudio总耗时*/

  uint64_t audioFileTimeLen; /*灌入音频文件的音频时长*/

  uint64_t audioTotalDuration; /*取到音频文件的音频总时长*/
  uint64_t audioAveDuration;   /*取到音频文件的音频平均时长*/

  uint64_t s50Value;  /*start()到started用时50ms以内*/
  uint64_t s100Value; /*start()到started用时100ms以内*/
  uint64_t s200Value;
  uint64_t s500Value;
  uint64_t s1000Value;
  uint64_t s2000Value;

  pthread_mutex_t mtx;
};

// 自定义事件回调参数
struct ParamCallBack {
 public:
  explicit ParamCallBack(ParamStruct *param) {
    userId = 0;
    memset(userInfo, 0, 8);
    tParam = param;
    pthread_mutex_init(&mtxWord, NULL);
    pthread_cond_init(&cvWord, NULL);
  };
  ~ParamCallBack() {
    tParam = NULL;
    pthread_mutex_destroy(&mtxWord);
    pthread_cond_destroy(&cvWord);
  };

  unsigned long userId;  // 这里用线程号
  char userInfo[8];

  pthread_mutex_t mtxWord;
  pthread_cond_t cvWord;

  struct timeval startTv;
  struct timeval startedTv;
  struct timeval firstTv;
  struct timeval completedTv;
  struct timeval closedTv;
  struct timeval failedTv;

  ParamStruct *tParam;
};

// 统计参数
struct ParamStatistics {
  ParamStatistics() {
    running = false;
    success_flag = false;
    failed_flag = false;
    audio_ms = 0;
    start_ms = 0;
    end_ms = 0;
    ave_ms = 0;
    s_cnt = 0;
  };

  bool running;
  bool success_flag;
  bool failed_flag;

  uint64_t audio_ms;
  uint64_t start_ms;
  uint64_t end_ms;
  uint64_t ave_ms;

  uint32_t s_cnt;
};
/**
 * 全局维护一个服务鉴权token和其对应的有效期时间戳，
 * 每次调用服务之前，首先判断token是否已经过期，
 * 如果已经过期，则根据AccessKey ID和AccessKey
 * Secret重新生成一个token，并更新这个全局的token和其有效期时间戳。
 *
 * 注意：不要每次调用服务之前都重新生成新token，只需在token即将过期时重新生成即可。所有的服务并发可共用一个token。
 */
extern std::string g_appkey;
extern std::string g_akId;
extern std::string g_akSecret;
extern std::string g_token;
extern std::string g_tokenDomain;
extern std::string g_api_version;
extern std::string g_url;
extern std::string g_vipServerDomain;
extern std::string g_vipServerTargetDomain;
extern std::string g_audio_path;
extern std::string g_voice;
extern int g_threads;
extern int g_cpu;
extern int g_sync_timeout;
extern bool g_save_audio;
extern std::string g_text;
extern std::string g_format;
extern int loop_timeout; /*循环运行的时间, 单位s*/
extern int loop_count; /*循环测试某音频文件的次数, 设置后loop_timeout无效*/
extern long g_expireTime;
//线程信号 
extern std::map<unsigned long, struct ParamStatistics *> g_statistics;
extern pthread_mutex_t params_mtx;
extern PROFILE_INFO *g_sys_info;

extern int profile_scan;
extern int cur_profile_scan;
extern bool global_sys;
extern PROFILE_INFO g_ave_percent;
extern PROFILE_INFO g_min_percent;
extern PROFILE_INFO g_max_percent;



void signal_handler_int(int signo);
void signal_handler_quit(int signo);
std::string timestamp_str();
void vectorSetParams(unsigned long pid, bool add,
                            struct ParamStatistics params);
void vectorSetResult(unsigned long pid, bool ret);
void vectorSetFailed(unsigned long pid, bool ret);
bool vectorGetRunning(unsigned long pid) ;
bool vectorGetFailed(unsigned long pid);
/**
 * 根据AccessKey ID和AccessKey Secret重新生成一个token，并获取其有效期时间戳
 */
int generateToken(std::string akId, std::string akSecret, std::string* token,
                  long* expireTime);

void *autoCloseFunc(void *arg);

int invalied_argv(int index, int argc);
unsigned int getAudioFileTimeMs(const int dataSize, const int sampleRate,
                                const int compressRate);
#ifdef __cplusplus
}
#endif
#endif